﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SSE657.BahMap.Common;
using SSE657.BahMap.DataAccess;

namespace SSE657.BahMap.Business
{
    public class RateManager
    {
        private IBAHDataConnector _dataConnector;

        public RateManager(IBAHDataConnector dataConnector)
        {
            this._dataConnector = dataConnector;
        }

        /// <summary>
        /// Returns an ordered list
        /// </summary>
        /// <param name="grade"></param>
        /// <param name="dependents"></param>
        /// <returns></returns>
        public List<RateData> GetRates(PayGrade grade, bool dependents)
        {
            List<RateData> rateData = new List<RateData>(_dataConnector.GetAreaRates(grade, dependents));
            rateData.InverseSort(new RateDataOrderByRateComparer());
            return rateData;
        }

        /// <summary>
        /// Returns an inversely sorted Dictionary of Rates (key) and rate percentile (value).
        /// </summary>
        /// <param name="grade"></param>
        /// <param name="dependents"></param>
        /// <returns></returns>
        public Dictionary<RateData, double> GetRatesPercentiles(PayGrade grade, bool dependents)
        {
            List<RateData> rates = this.GetRates(grade, dependents);
            double max = rates[0].Rate;
            double min = rates[rates.Count - 1].Rate;

            Dictionary<RateData, double> percentileRates = new Dictionary<RateData, double>();
            foreach (RateData rate in rates)
            {
                percentileRates.Add(rate, MathHelper.CalculatePercentile(min, max, rate.Rate));
            }

            return percentileRates;
        }

        /// <summary>
        /// Returns a KeyValue pair where the key is the rate and the value is the percentile
        /// </summary>
        /// <param name="zip"></param>
        /// <param name="grade"></param>
        /// <param name="dependents"></param>
        /// <returns></returns>
        public KeyValuePair<double, double> GetRatePercentile(int zip, PayGrade grade, bool dependents)
        {
            double min;
            double max;
            double rate;
            _dataConnector.GetRateAndRange(grade, dependents, zip, out rate, out min, out max);

            return new KeyValuePair<double, double>(rate, MathHelper.CalculatePercentile(min, max, rate));
        }

        /// <summary>
        /// Returns a lookup of all BAH rates by PayGrade and dependents status for the specified MHA.
        /// </summary>
        /// <param name="mha"></param>
        /// <returns></returns>
        public Dictionary<PayGrade, Dictionary<bool, RateData>> GetRates(string mha)
        {
            IEnumerable<RateData> data = _dataConnector.GetRates(mha);
            return LoadDictionary(data);
        }

        /// <summary>
        /// Returns a lookup of all BAH rates by PayGrade and dependents status for the specified ZIP code.
        /// </summary>
        /// <param name="zip"></param>
        /// <returns></returns>
        public Dictionary<PayGrade, Dictionary<bool, RateData>> GetRates(int zip)
        {
            IEnumerable<RateData> data = _dataConnector.GetRates(zip);
            return LoadDictionary(data);
        }

        private static Dictionary<PayGrade, Dictionary<bool, RateData>> LoadDictionary(IEnumerable<RateData> data)
        {
            Dictionary<PayGrade, Dictionary<bool, RateData>> results = new Dictionary<PayGrade, Dictionary<bool, RateData>>();

            foreach (RateData rate in data)
            {
                if (!results.ContainsKey(rate.Grade))
                    results.Add(rate.Grade, new Dictionary<bool, RateData>());
                results[rate.Grade].Add(rate.Dependents, rate);
            }

            return results;
        }
    }
}
